package zhongbo.java.air.dictionary.service.impl;

import cn.hutool.core.text.CharSequenceUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import zhongbo.java.air.common.exception.BusinessException;
import zhongbo.java.air.common.exception.ExceptionCode;
import zhongbo.java.air.common.exception.NoStackLogException;
import zhongbo.java.air.common.util.NumberUtil;
import zhongbo.java.air.common.vo.PageVo;
import zhongbo.java.air.dictionary.mapper.AirPortMapper;
import zhongbo.java.air.dictionary.model.entities.AirPort;
import zhongbo.java.air.dictionary.service.IAirPortService;


import java.util.Date;
import java.util.Objects;

/**
 * 机场信息服务实现类
 *
 * @author WeiJin
 * @version 1.0
 * @date 2025/3/31 11:16
 */
@Service
public class AirPortServiceImpl implements IAirPortService {

    @Autowired
    private AirPortMapper airPortMapper;

    @Override
    public AirPort saveAirPort(AirPort airPort) {
        // 参数校验
        validAirPort(airPort);
        // 校验唯一性
        AirPort dataAirPort = queryByIcaoCodeOrIataCode(airPort.getIcaoCode(), airPort.getIataCode());
        // 新增查询出来就说明icaoCode或iataCode已存在
        if (Objects.nonNull(dataAirPort)) {
            throw new BusinessException(ExceptionCode.ICAO_CODE_OR_IATA_CODE_EXISTED);
        }
        // 新增时指定当前日期为创建时间和修改时间
        airPort.setCreateTime(new Date());
        airPort.setUpdateTime(new Date());
        int inserted = airPortMapper.insert(airPort);
        // 根据影响表中记录数做出相应的返回
        if (inserted > 0) {
            return airPort;
        }
        throw new BusinessException(ExceptionCode.SAVE_FAILED);
    }

    @Override
    public String delAirPort(String id) {
        int deleted = airPortMapper.deleteById(id);
        // 影响数据库记录条数做出相应的返回
        if (deleted > 0) {
            return id;
        }
        throw new BusinessException(ExceptionCode.DELETE_FAILED);
    }

    @Override
    public AirPort modifyAirPort(AirPort airPort) {
        // 参数校验
        validAirPort(airPort);
        // 单独校验 id
        if (CharSequenceUtil.isBlank(airPort.getId())) {
            throw new BusinessException(ExceptionCode.ID_NOT_NULL);
        }
        // 修改时先查询要修改的机场id是否存在
        if (Objects.isNull(queryById(airPort.getId()))) {
            throw new BusinessException(ExceptionCode.AIR_PORT_NOT_EXIST);
        }
        // 校验唯一性
        AirPort dataAirPort = queryByIcaoCodeOrIataCode(airPort.getIcaoCode(), airPort.getIataCode());
        // 数据库中根据icaoCode 或 iataCode 查询出来的数据的id和用户要修改数据的id不一致，说明，已经存在
        if (Objects.nonNull(dataAirPort)
                && !dataAirPort.getId().equals(airPort.getId())) {
            throw new BusinessException(ExceptionCode.ICAO_CODE_OR_IATA_CODE_EXISTED);
        }

        // 修改时给当前时间为修改时间
        airPort.setUpdateTime(new Date());
        int updated = airPortMapper.updateById(airPort);
        // 修改成功，查询出修改后的信息，返回
        if (updated > 0) {
            return queryById(airPort.getId());
        }
        // 修改失败 抛出异常
        throw new BusinessException(ExceptionCode.UPDATE_FAILED);

    }

    @Override
    public AirPort queryById(String id) {
        AirPort airPort = airPortMapper.selectById(id);
        // 查询不到，抛出不存在异常
        if (Objects.isNull(airPort)) {
            throw new BusinessException(ExceptionCode.CURRENT_ID_NOT_EXIST);
        }
        return airPort;
    }

    @Override
    public PageVo<AirPort> pageAirPort(Integer pageNumber, Integer pageSize, String name, String status, String orderBy,
                                       Boolean orderType) {
        QueryWrapper<AirPort> wrapper = new QueryWrapper<>();
        IPage<AirPort> page = new Page<>(pageNumber, pageSize);
        // 机场全称不为空，添加查询条件
        wrapper.eq(CharSequenceUtil.isNotBlank(name), "name", name);

        // 机场状态不为空，添加查询条件
        wrapper.eq(CharSequenceUtil.isNotBlank(status), "status", status);
        // 排序字段不为空，添加相应的排序
        if (CharSequenceUtil.isNotBlank(orderBy)) {
            // 升序
            if (Boolean.TRUE.equals(orderType)) {
                wrapper.orderByAsc(orderBy);
            } else {
                // 降序
                wrapper.orderByDesc(orderBy);
            }
        }
        // 查询
        IPage<AirPort> airPortPage = airPortMapper.selectPage(page, wrapper);
        return new PageVo<>(airPortPage);
    }

    @Override
    public AirPort queryByIcaoCodeOrIataCode(String icaoCode, String iataCode) {
        // icaoCode 和iataCode不存在直接返回null，不查询
        if (CharSequenceUtil.isBlank(icaoCode) && CharSequenceUtil.isBlank(iataCode)) {
            return null;
        }
        // 构建查询语句
        LambdaQueryWrapper<AirPort> wrapper = new LambdaQueryWrapper<AirPort>()
                // icaoCode存在才构造sql
                .eq(CharSequenceUtil.isNotBlank(icaoCode), AirPort::getIcaoCode, icaoCode)
                .or()
                // iataCode存在才构造sql
                .eq(CharSequenceUtil.isNotBlank(iataCode), AirPort::getIataCode, iataCode);
        return airPortMapper.selectOne(wrapper);
    }

    private void validAirPort(AirPort airPort) {
        // 非空校验
        if (Objects.isNull(airPort)) {
            throw new NoStackLogException("请求参数不能为空");
        }
        if (CharSequenceUtil.isBlank(airPort.getIcaoCode())) {
            throw new NoStackLogException("icaoCode 不能为空");
        }
        if (CharSequenceUtil.isBlank(airPort.getIataCode())) {
            throw new NoStackLogException("iataCode 不能为空");
        }
        if (CharSequenceUtil.isBlank(airPort.getName())) {
            throw new NoStackLogException("name 不能为空");
        }
        if (Objects.isNull(airPort.getLatitude())) {
            throw new NoStackLogException("latitude 不能为空");
        }
        if (Objects.isNull(airPort.getLongitude())) {
            throw new NoStackLogException("longitude 不能为空");
        }
        if (Objects.isNull(airPort.getStatus())) {
            throw new NoStackLogException("status 不能为空");
        }
        if (CharSequenceUtil.isBlank(airPort.getTimezone())) {
            throw new NoStackLogException("timezone 不能为空");
        }
        // 长度校验
        if (airPort.getIcaoCode().length() > 4) {
            throw new NoStackLogException("参数icaoCode长度最长为4");
        }
        if (airPort.getIataCode().length() > 3) {
            throw new NoStackLogException("参数iataCode长度最长为3");
        }
        if (airPort.getName().length() > 100) {
            throw new NoStackLogException("参数name长度最长为100");
        }
        // 经纬度小数校验
        if (NumberUtil.validDecimal(airPort.getLatitude(), 3, 6)) {
            throw new NoStackLogException("参数latitude整数部分最多3位，小数部分多6位");
        }
        if (NumberUtil.validDecimal(airPort.getLongitude(), 3, 6)) {
            throw new NoStackLogException("参数longitude整数部分最多3位，小数部分多6位");
        }
        if (airPort.getTimezone().length() > 50) {
            throw new NoStackLogException("参数timezone长度最长为50");
        }
    }
}
